import { command, ExecaChildProcess } from 'execa';
import winston from 'winston';
import {
  ensurePortAvailable,
  killProcess,
  killProcessAll,
} from '../utils/kill_port';
import { PathFinder } from '../utils/path_manager';
import log from 'electron-log/node';
import { run } from '../utils/shell';
import FileUtils from '../utils/FileUtils';

const SERVER_STARTUP_TIMEOUT = 5000; // 设定超时时间为5秒
const LOCAL_HOST = '127.0.0.1';
// const LOCAL_HOST = "0.0.0.0";

// 创建一个 winston 日志记录器
export const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
    winston.format.printf(
      (info) =>
        `${info.timestamp} [${info.level.toUpperCase()}] ${info.message}`,
    ),
  ),
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: FileUtils.getDailyLogFile('server') }),
  ],
});

log.info('日志系统初始化完成  ' + FileUtils.getDailyLogFile('server'));

// 存储 Python 进程的全局变量
let pythonProcess: ExecaChildProcess | null = null;

// 类型定义
type ServerConfig = {
  port: number;
  pythonModule: string;
  logLevel: string;
};

// 默认配置
const DEFAULT_CONFIG: ServerConfig = {
  port: 8000,
  pythonModule: 'pup_core',
  logLevel: 'info',
};

/**
 * 启动 Python WebSocket 服务器
 * @param customConfig 自定义配置
 * @param func
 */
export async function startPythonServer(
  customConfig: Partial<ServerConfig> = {},
  func?: () => void,
): Promise<void> {
  // 合并配置
  const config: ServerConfig = { ...DEFAULT_CONFIG, ...customConfig };

  // 清理任何现有进程
  await stopPythonServer();

  // 获取关键路径
  log.info('=== 路径验证 ===');
  log.info('项目根目录:' + PathFinder.PROJECT_ROOT);
  log.info('虚拟环境:' + PathFinder.VENV_PATH);
  log.info('Python:' + PathFinder.PYTHON_PATH);
  log.info('启动脚本:' + PathFinder.STARTUP_SCRIPT);

  log.info('启动 Python 服务器...');

  const pythonExec = PathFinder.PYTHON_PATH;

  try {
    // 检查 Python 版本并确保端口可用
    await checkPythonVersion(pythonExec);

    const portAvailable = await ensurePortAvailable(config.port);
    const portAvailable2 = await ensurePortAvailable(5555);

    if (!portAvailable || !portAvailable2) {
      throw new Error(`端口 ${config.port} 不可用`);
    }

    // 准备启动参数
    const args = [
      '-m',
      config.pythonModule,
      '--host',
      LOCAL_HOST,
      '--port',
      config.port.toString(),
      // '--reload',
      '--log-level',
      config.logLevel,
    ];

    log.info(`启动命令: ${pythonExec} ${args.join(' ')}`);

    // 设置环境变量，确保 Python 输出不缓冲
    const env = {
      ...process.env,
      PYTHONUNBUFFERED: '1', // 禁用 Python 输出缓冲
    };

    const commandStr = [pythonExec, ...args].join(' ');

    pythonProcess = command(commandStr, {
      stdio: ['ignore', 'pipe', 'pipe'],
      shell: false,
      cleanup: true,
      env,
    });

    // // 使用 execa 启动进程
    // pythonProcess = execa(pythonExec, args, {
    //   stdio: ['ignore', 'pipe', 'pipe'],
    //   shell: false,
    //   cleanup: true,
    //   env: env, // 设置环境变量
    // });

    if (!pythonProcess.pid) {
      throw new Error('进程启动失败');
    }

    log.info(`服务器 PID: ${pythonProcess.pid}`);

    // 直接将 Python 进程的输出流连接到 Node.js 的标准输出和标准错误流
    // pythonProcess.stdout?.pipe(process.stdout);  // 将标准输出连接到 Node.js 控制台
    // pythonProcess.stderr?.pipe(process.stderr);  // 将错误输出连接到 Node.js 控制台

    // 用于追踪服务器是否启动的标志
    let serverStarted = false;

    // 等待服务器启动
    const serverStartupPromise = new Promise<void>((resolve, reject) => {
      if (pythonProcess) {
        // 监听 stdout，等待启动完成的标志
        pythonProcess.stdout?.on('data', (data: Buffer) => {
          const output = data.toString().trim();
          logger.info(
            output,
          );

          // 检查启动成功的标志
          if (output.includes('Notifications WebSocket route loaded')) {
            serverStarted = true;
            log.info('服务器启动成功');
            resolve();
          }
        });

        // 处理错误输出
        pythonProcess.stderr?.on('data', (data: Buffer) => {
          const errorOutput = data.toString().trim();
          logger.error(
            errorOutput,
          );

          // 检查启动成功的标志
          if (
            errorOutput.includes(
              'Uvicorn running on http://' + LOCAL_HOST + ':8000',
            )
          ) {
            serverStarted = true;
            log.info('服务器启动成功');
            resolve();
          }
        });

        // 处理进程退出
        pythonProcess.on('close', (code) => {
          const msg = `服务器退出，代码: ${code}`;
          if (code !== 0) {
            log.error(msg);
            if (!serverStarted) {
              reject(new Error(msg));
            }
          } else {
            log.info(msg);
          }
          cleanup();
        });

        // 处理进程错误
        pythonProcess.on('error', (err) => {
          log.error(`进程错误: ${err.message}`);
          cleanup();
          reject(err);
        });
      } else {
        log.error('Python 进程未启动');
      }
    });

    // 设置超时
    const timeoutPromise = new Promise<void>((_, reject) => {
      setTimeout(() => {
        if (!serverStarted) {
          reject(new Error('服务器启动超时'));
        }
      }, SERVER_STARTUP_TIMEOUT);
    });

    // 等待服务器启动或超时
    await Promise.race([serverStartupPromise, timeoutPromise]);

    if (func) {
      await func();
    }
  } catch (err) {
    if (err instanceof Error) {
      log.error(`服务器启动时发生错误: ${err.message}`);
      cleanup();
      throw new Error(`服务器启动时发生错误: ${err.message}`);
    } else {
      log.error(`服务器启动时发生未知错误: ${String(err)}`);
      cleanup();
      throw new Error(`服务器启动时发生未知错误: ${String(err)}`);
    }
  }
}

/**
 * 停止 Python WebSocket 服务器
 */
export async function stopPythonServer(): Promise<void> {
  if (pythonProcess && pythonProcess.pid) {
    log.info(`正在停止 pup_core 服务器 (PID: ${pythonProcess.pid})...`);

    try {
      log.info(`尝试终止进程 PID: ${pythonProcess.pid}`);
      // 首先尝试优雅地终止
      pythonProcess.kill('SIGTERM');

      // 等待进程完全退出
      const result = await pythonProcess;
      const exitCode = result.exitCode;

      if (exitCode !== 0) {
        log.error(`进程退出码: ${exitCode}`);
        // 如果进程未正常退出，强制终止
        if (!pythonProcess.killed) {
          log.warn('进程未成功终止，尝试强制终止');
          await killProcess(pythonProcess.pid);
        }
      }
    } catch (err) {
      log.error(`停止 pup_core 服务器时出错: ${err}`);
    } finally {
      cleanup();
    }
  }
}

/**
 * 清理资源
 */
function cleanup(): void {
  if (pythonProcess && !pythonProcess.killed) {
    try {
      log.info('清理资源，强制终止进程...');
      pythonProcess.kill('SIGKILL');
    } catch (err) {
      log.error(`强制终止进程时出错: ${err}`);
    }
  }

  pythonProcess = null;
}

/**
 * 检查 Python 版本
 */
async function checkPythonVersion(pythonPath: string): Promise<void> {
  try {
    const { stdout } = await run(`${pythonPath} --version`);
    log.info(`Python 版本: ${stdout.trim()}`);
  } catch (error) {
    log.error(`检查 Python 版本失败: ${error}`);
    throw new Error(`检查 Python 版本失败: ${error}`);
  }
}
